﻿using System;
using SlimDX.Direct2D;
using SlimDX.Direct3D11;

namespace JamesZhao.Engine.Graphics
{
    /// <summary>
    /// Encapuslates a d3d device
    /// Used to cache the ImmediateContext
    /// Each d3ddevice.ImmediateContext translates into a d3d getimmediatecontext call
    /// </summary>
    public class GraphicsDevice
    {
        private Viewport _viewport;

        public GraphicsDevice(Device device)
        {
            Device = device;
            ImmediateContext = device.ImmediateContext;
            AdditiveBlendState = CreateAdditiveBlendState(this);

            D2DFactory = new Factory();
        }

        public DeviceContext ImmediateContext { get; private set; }

        public Device Device { get; private set; }
        
        public Viewport Viewport
        {
            get { return _viewport; }
            set
            {
                _viewport = value;
                ImmediateContext.Rasterizer.SetViewports(value);
            }
        }

        public void ApplyTemporaryViewport(Viewport viewport)
        {
            ImmediateContext.Rasterizer.SetViewports(viewport);
        }

        public void RevertViewport()
        {
            ImmediateContext.Rasterizer.SetViewports(_viewport);
        }

        public BlendState AdditiveBlendState { get; private set; }

        public Factory D2DFactory { get; set; }

        private static BlendState CreateAdditiveBlendState(GraphicsDevice device)
        {
            
            var blendDesc = new BlendStateDescription
            {
                IndependentBlendEnable = true,
                AlphaToCoverageEnable = false,
            };
            blendDesc.RenderTargets[0] = new RenderTargetBlendDescription
                                             {
                                                 BlendEnable = true,
                                                 BlendOperation = BlendOperation.Add,
                                                 SourceBlend = BlendOption.One,
                                                 DestinationBlend = BlendOption.One,
                                                 BlendOperationAlpha = BlendOperation.Add,
                                                 DestinationBlendAlpha = BlendOption.One,
                                                 SourceBlendAlpha = BlendOption.One,
                                                 RenderTargetWriteMask = 0
                                             };
            return BlendState.FromDescription(device.Device, blendDesc);
        }
    }
}